/**
 * Symbol 就是一个基本数据类型
 *   可以做为对象的一个 key
 */

///////////////////////////////////////////////////////////////
// 语法
///////////////////////////////////////////////////////////////

// 第一种方法直接使用Symbol构造函数
var s1 = Symbol();
// 为创建的Symbol对象指定一个名称
var s2 = Symbol("test");
// 使用这种方法，每次创建出来的Symbol对象都是不一样的
var s3 = Symbol("test");
console.log(s1 === s2); // 将返回false
console.log(s2 === s3); // 将返回false

// 第二种方法，使用Symbol.for方法来创建Symbol实例
// 使用Symbol.for方法来创建一个Symbol实例的时候，
// 系统首先会在一个全局的注册表中查找是否有相同Key名称的Symbol被创建了，如果找到，就返回已经存在的对象
// 否则，将创建一个全新的对象
s1 = Symbol.for("test");
s2 = Symbol.for("test");
console.log(s1 == s2); //will return true
console.log(s1 == s3); // will return false，因为s3是通过Symbol调用产生的

///////////////////////////////////////////////////////////////
// 使用场景
///////////////////////////////////////////////////////////////

// 使用Symbol来定义类的属性(当使用Symbol作为属性名的时候，一定要用[]来进行引用，如果你用.（点号）进行引用，那么产生的属性名实际是一个字符串，和Symbol对象本身没一点关系)
var a = {};
var ss1 = Symbol("test");
a[ss1] = "hello world!";
console.log(a[ss1]); // "Hello World!"

// 遍历使用Symbol来定义的属性
// 因为Symbol对象不是一个字符串，所以原先的Object.getOwnPropertyNames()方法并不会返回它们，需要使用专门的Object.getOwnPropertySymbols()方法来访问它们
// Reflect.ownKeys(obj) 可以获取对象上 包含 Symbol 的所有属性 但是不包括继承的属性
var ss2 = Symbol("testfunc");
a[ss2] = function () {
    console.log("Test function");
};
a.name = 'object';
//below code will return []
console.log(Object.getOwnPropertyNames(a));
//below code will return [Symbol(test), Symbol(testfunc)]
console.log(Object.getOwnPropertySymbols(a));
console.log(Reflect.ownKeys(a));

// 消除魔术字符串
// # 引入Symbol前的代码
// # 在这个代码中es, ch就是魔术字符串
// # 当你在调用这个函数的时候，必须确保输入的参数是一个有效的魔术值
function getHello_es5(country){
    switch(country){
        case "es":
            return "Holla";
        case "ch":
            return "你好";
        default:
            return "Hello";
    }
}
console.log(getHello_es5("es"));
console.log(getHello_es5("ch"));
// # 引入Symbol之后的代码
// # 在这个代码中es, ch不再是一个具体的字符串
// # 因此不管在COUNTRY_CODE中如何修改es, ch的定义，调用方的代码都不需要修改
const COUNTRY_CODE= {
    es: Symbol(),
    ch: Symbol()
};
function getHello_es6(country){
    switch(country){
        case COUNTRY_CODE.es:
            return "Holla";
        case COUNTRY_CODE.ch:
            return "你好";
        default:
            return "Hello"
    }
}
console.log(getHello_es6(COUNTRY_CODE.es));
console.log(getHello_es6(COUNTRY_CODE.ch));
